#include "Core/Device.h"
#include "Loaders/Loaders.h"
#include "GL/glfw.h"
#include <sstream>

using namespace std;

namespace blue {

  SINGLETON_IMPL(Device)

  Device::Device() : _run(false)
  {
    glfwInit();
  }

  Device::~Device()
  {
    if(_run) closeDevice();
    EventManager::destroy();
    Renderer::destroy();
    ResourceManager::destroy();
    MediaManager::destroy();
  }

  void GLFWCALL eventWindowResize(int width, int height)
  {
    Device::instance()->resize(width, height, false);
  }

  void Device::init(int width, int height, bool fullscreen)
  {
    _size.X = width;
    _size.Y = height;
    _fullscreen = fullscreen;
    _run = true;
    _FPS = 60;
    _current_time = _fps_timer = 0;

    if(_fullscreen) glfwOpenWindow(width, height, 8, 8, 8, 8, 32, 32, GLFW_FULLSCREEN);
    else glfwOpenWindow(width, height, 8, 8, 8, 8, 32, 32, GLFW_WINDOW);

    glfwSetWindowSizeCallback(eventWindowResize);

    Renderer::instance()->init();
    Renderer::instance()->initExtensions();
    EventManager::instance()->init();

    registerLoaders();
  }

  Vector2i Device::getSize()
  {
    return _size;
  }

  void Device::resize(int width, int height, bool effective)
  {
    _size.X = width;
    _size.Y = height;
    Renderer::instance()->resize(width, height);
    if(effective) glfwSetWindowSize(width, height);
  }

  void Device::setWindowPos(int x, int y)
  {
    glfwSetWindowPos(x, y);
  }

  void Device::sleep(double time)
  {
    glfwSleep(time);
  }

  bool Device::isFullScreen() const
  {
    return _fullscreen;
  }

  void Device::setWindowTitle(const std::string title, bool giveFPS)
  {
    _FPS++;

    _current_time = glfwGetTime();

    if(_current_time - _fps_timer >= 1.0)
      {
        if(giveFPS)
	  {
            _title = title + " - FPS : ";
            ostringstream s;
            s << _FPS << flush;
            _title += s.str();
	  }
        else
	  _title = title;

        glfwSetWindowTitle(_title.c_str());

        _FPS = 0;
        _fps_timer = glfwGetTime();
      }
  }

  void Device::setMousePos(int x, int y)
  {
    glfwSetMousePos(x, y);
  }

  void Device::showCursor(bool show)
  {
    if(show) glfwEnable(GLFW_MOUSE_CURSOR);
    else glfwDisable(GLFW_MOUSE_CURSOR);
  }

  bool Device::run() const
  {
    return _run;
  }

  void Device::closeDevice()
  {
    _run = false;
    unregisterLoaders();
    glfwTerminate();
  }

  Renderer *Device::getRenderer() const
  {
    return Renderer::instance();
  }

  EventManager *Device::getEventManager() const
  {
    return EventManager::instance();
  }

  ResourceManager *Device::getResourceManager() const
  {
    return ResourceManager::instance();
  }

  MediaManager *Device::getMediaManager() const
  {
    return MediaManager::instance();
  }

}
